package com.atmilan.quartz.sync.push.europe.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSONArray;
import com.atmilan.quartz.constant.enums.ProductTypeEnum;
import com.atmilan.quartz.model.entity.BuyerProductDO;
import com.atmilan.quartz.model.entity.buyer.BuyerBrand;
import com.atmilan.quartz.model.entity.buyer.BuyerProductSkuMerged;
import com.atmilan.quartz.model.entity.europe.EuropeBrand;
import com.atmilan.quartz.model.entity.europe.EuropeProduct;
import com.atmilan.quartz.model.entity.europe.EuropeProductSkuMerged;
import com.atmilan.quartz.sync.pull.europe.service.IEuropeBrandService;
import com.atmilan.quartz.sync.pull.europe.service.IEuropeProductService;
import com.atmilan.quartz.sync.pull.europe.service.IEuropeProductSkuMergedService;
import com.atmilan.quartz.sync.pull.europe.service.IEuropeProductSkuService;
import com.atmilan.quartz.sync.push.europe.service.IEuropePushService;
import com.atmilan.quartz.sync.push.service.IProductListenerService;
import com.atmilan.quartz.utils.PriceUtil;
import com.atmilan.quartz.utils.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class EuropePushServiceImpl implements IEuropePushService {
    ExecutorService service = Executors.newFixedThreadPool(18);
    static final String postBrandUrl = "/api/open/store/brand/import";
    static final String postEuropeBrandUrl = "/api/open/store/europeBrand/import";
    @Value("${crmeb.domain}")
    private String crmebApiDomain;

    int countPushed = 0;
    int countStart = 0;

    Lock lock = new ReentrantLock();

    @Autowired
    IEuropeBrandService europeBrandService;

    @Autowired
    PriceUtil priceUtil;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    IEuropeProductService europeProductService;
    @Autowired
    IEuropeProductSkuService europeProductSkuService;
    @Autowired
    IEuropeProductSkuMergedService europeProductSkuMergedService;
    @Autowired
    IProductListenerService productListenerService;

    @Override
    public boolean pushBrand() {
        List<EuropeBrand> europeBrandList = europeBrandService.list();
        List<BuyerBrand> buyerBrandList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(europeBrandList)) {
            //将EuropeBrand转换成BuyerBrand,使用Buyer接口推送EuropeBrand数据
            europeBrandList.forEach(vo -> {
                BuyerBrand buyerBrand = new BuyerBrand();
                buyerBrand.setBrandId(vo.getBrandId());
                buyerBrand.setBrandName(vo.getBrandName());
                buyerBrand.setCreateTime(vo.getCreateTime());
                buyerBrand.setEditTime(vo.getEditTime());
                buyerBrand.setBrandZm(vo.getBrandZm());//品牌首字母
                buyerBrandList.add(buyerBrand);
            });

            log.warn("{} - {} -------- start push EuropeBrandList {} ");
            String ret = HttpUtil.post(crmebApiDomain + postEuropeBrandUrl, JSONArray.toJSONString(buyerBrandList));
            log.warn("{} - {} push brandList: {} ret  =  {}", buyerBrandList);
        }
        return true;
    }

    @Override
    public boolean pushAllEuropeProduct() {
        if (lock.tryLock()) {
            try {
                pushEuropeProduct();
            } finally {
                lock.unlock();
            }
        } else {
            log.error("已经有线程在同步商品, 不要重复执行!");
        }
        return true;
    }

    public Boolean pushEuropeProduct() {
        long start = System.currentTimeMillis();
        int pageNo = 1;
        int pageSize = 300;

        LambdaQueryWrapper<EuropeProduct> lambdaQueryWrapper = Wrappers.<EuropeProduct>lambdaQuery()
                .gt(EuropeProduct::getPrice, 0)
                .gt(EuropeProduct::getStock, 0)
                ;
        int count = europeProductService.count(lambdaQueryWrapper);
        
        int maxPage = count == 0 ? 0 : (count / pageSize) + 1;
        log.info("--------------- 开始分页查询europe商品源数据, 本次更新总条数为: {} ---------------", count);
        while(pageNo <= maxPage) {
            // 分页查询buyer商品
            PageHelper.startPage(pageNo, pageSize);
            List<EuropeProduct> europeProducts = europeProductService.list(lambdaQueryWrapper);
            PageInfo<EuropeProduct> iPage = PageInfo.of(europeProducts);

            int tempPageNo = pageNo;
            service.execute(() -> {
                try {
                    List<EuropeProduct> itemList = iPage.getList();
                    if (!CollectionUtils.isEmpty(itemList)) {
                        long now = System.currentTimeMillis();
                        log.warn("--------------- 第: {} 页 --------------- 总页数: {} --------------- 平均每页耗时: {} 秒", tempPageNo, maxPage, ((now-start) / tempPageNo) / 1000);
                        itemList.forEach(product -> {
                            processOne(product);
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            
            pageNo++;
        }
        
        return true;
    }

    private void processOne(EuropeProduct product) {
        // 这里从 sku_merged 表里取，已经去重并且合并了库存
        List<EuropeProductSkuMerged> list = europeProductSkuMergedService.list(Wrappers.<EuropeProductSkuMerged>lambdaQuery()
                .eq(EuropeProductSkuMerged::getGoodsId, product.getGoodId())
                //.eq(EuropeProductSkuMerged::getQihuo, 0)
                .ne(EuropeProductSkuMerged::getSize, "")
                .isNotNull(EuropeProductSkuMerged::getSize)
                .gt(EuropeProductSkuMerged::getStock, 0));
        product.setSkuMergedList(list);

        long s = System.currentTimeMillis();
        try {
            BuyerProductDO buyerProduct = new BuyerProductDO();
            buyerProduct.setGoodsId(product.getGoodId() + "");
            buyerProduct.setIsEurope(ProductTypeEnum.EUROPE.getCode());
            buyerProduct.setSalePrice(product.getPrice().toString());
            buyerProduct.setStock(product.getStock());
            buyerProduct.setGoodsImg(product.getGoodsImg());
            List<BuyerProductSkuMerged> bpsm = new ArrayList<>();
            list.forEach(skuMerged -> {
                BuyerProductSkuMerged buyerProductSkuMerged = new BuyerProductSkuMerged();
                BeanUtils.copyProperties(skuMerged, buyerProductSkuMerged);
                bpsm.add(buyerProductSkuMerged);
            });
            buyerProduct.setSkuList(bpsm);
            buyerProduct.setUpdateFlag(product.getUpdateFlag());
            // 新增冗余参数
            buyerProduct.setPrice(product.getPrice());
            buyerProduct.setReferencePrice(product.getReferencePrice());
            buyerProduct.setGoodsName(product.getGoodsName());
            buyerProduct.setCode(product.getCode());
            buyerProduct.setBrandId(product.getBrandId()+"");
            buyerProduct.setCategoryId(product.getCategoryId());
            buyerProduct.setGallery(product.getGallery());
            buyerProduct.setSupplierId(product.getSupplierId());
            productListenerService.receiveProductMsg(buyerProduct);
        } catch (Exception ex) {
            log.error("redis exception! e: ", ex);
        } finally {
            log.warn("{} -- {} --------- processOne product:{}, ct= {}", countStart, countPushed, product.getGoodId(), (System.currentTimeMillis() - s));
        }
    }
}
